/* 
 * 		Raj Akula
 * 		CSC 594 
 * 		Android Application Development
 * 		10-20-2011
 *      This application builds on top of Pay Calculator 1.0
 *      It adds some level of security by requiring user to 
 *      enter a username and password thats valid before 
 *      they can do any sort of calculations.. 
 * 
 */



package nku.csc594.project2;


import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.text.DecimalFormat;

import nku.csc594.R;

import android.app.Activity;
import android.app.AlertDialog;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TabHost;
import android.widget.Toast;

public class PayCalculator2Activity extends Activity {
	
	//Hash Map for users
	java.util.Map<String, String> users = new java.util.HashMap<String, String>();
	
	//Widgets
	Button btnCalc, btnClear, btnLogIn;
    EditText etHours, etPayRate, etTotalPay, etFedWH, etStateWH, etNetPay, etUserName, etPassword;
	
    //Tax Values
    private static final Float fedTaxRate = new Float(.22);
	private static final Float stateTaxRate = new Float(.022);
	private static final Float overTimePayRate = new Float(1.5);
	private final static String NOTES="notes.txt";
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
    	
    	//Sets up screen with tabs... 
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		TabHost tabs=(TabHost)findViewById(R.id.tabhost);
		tabs.setup();
		TabHost.TabSpec spec=tabs.newTabSpec(getResources().getString(R.string.calculateTag));
		spec.setContent(R.id.LinearTableLayout2);
		spec.setIndicator("Calculate");
		tabs.addTab(spec);
		spec=tabs.newTabSpec(getResources().getString(R.string.loginTag));
		spec.setContent(R.id.LinearTableLayout1);
		spec.setIndicator("Login");
		tabs.addTab(spec);
		tabs.setCurrentTabByTag(getResources().getString(R.string.loginTag));
		
		
		//Goes and gets the usernames and passwords
		this.readUserNamesAndPasswords();
		
		//Sets Buttons
        btnCalc = (Button)findViewById(R.id.button1);
        btnClear = (Button)findViewById(R.id.button2);
        btnLogIn = (Button)findViewById(R.id.button3);
        
        //Sets EditTextView's
        etHours = (EditText)findViewById(R.id.hours);
        etPayRate = (EditText)findViewById(R.id.payRate);
        etTotalPay = (EditText)findViewById(R.id.totalPay);
        etFedWH = (EditText)findViewById(R.id.fedWH);
        etStateWH = (EditText)findViewById(R.id.stateWH);
        etNetPay = (EditText)findViewById(R.id.netPay);
        etUserName = (EditText)findViewById(R.id.username);
        etPassword = (EditText)findViewById(R.id.password);
        
        getSavedInformation();
        

    }
    
    //Checks to see if there is a file to read out their and if there is it reads it. 
    //One assumption that i made is get the last successful save.. 
    //So if user opens the app and clears the hours and payRate, it will keep
    //his last hours and payRate he didn't clear. But unless he login's 
    //he can't do the calculate.. In comments i placed a delete option which 
    //can be enabled if the don't want that to happen... 
    public void getSavedInformation(){
		try {
			InputStream in=openFileInput(NOTES);
			if (in!=null) {
				InputStreamReader tmp=new InputStreamReader(in);
				BufferedReader reader=new BufferedReader(tmp);
				String tempString = "";
				String arrayTempString[];
				tempString = reader.readLine().toString();
				arrayTempString = tempString.split(",");
				this.etHours.setText(arrayTempString[0]);
				this.etPayRate.setText(arrayTempString[1]);
				in.close();
			}
		}
		catch (java.io.FileNotFoundException e) {
			// that's OK, we probably haven't created it yet
		}
		catch (Throwable t) {
			Toast
				.makeText(this, "Exception: "+t.toString(), Toast.LENGTH_LONG)
				.show();
		}
    }
    
    
    //Loops through and maps the usernames with the passwords... 
    public void readUserNamesAndPasswords(){
    	String usernames[] = getResources().getStringArray(R.array.usernames);
    	String passwords[] = getResources().getStringArray(R.array.passwords);
    	if(usernames.length != passwords.length){
    		new AlertDialog.Builder(this)
    			.setTitle(getResources().getString(R.string.readingAccountsErrorTitle))
    			.setMessage(getResources().getString(R.string.readingAccountsErrorMessage))
    			.setNeutralButton(getResources().getString(R.string.neutralButton1), null)
  		  		.show();
    	}
    	else{
    		for(int i = 0; i < usernames.length; i++){
    			this.users.put(usernames[i], passwords[i]);
    		}
    	}
    }
    
    //Does calculations for the 4 output text views... 
    public void doCalculate(View view){
    	if(checkForErrorsOnCalculate() == false){	
    		// Parsing Input
    		Float hours = Float.parseFloat(etHours.getText().toString());
    		Float payRate = Float.parseFloat(etPayRate.getText().toString());
    		
    		//Function Calls to calculate values
    		Float totalPay = getTotalPay(hours, payRate);
    		Float fedWH = getFederalTaxRate(totalPay);
    		Float stateWH = getStateTaxRate(totalPay);
    		
    		//In case we add more deductions.. .
    		Float deductions[] = new Float[2];
    		deductions[0] = fedWH;
    		deductions[1] = stateWH;
    		
    		//Ending total net calculation
    		Float totalNet = this.getNetPay(totalPay, this.getTotalDeductions(deductions));
    		
    		//Format for output... I prefer using this since HOURS isn't a currency value.. but customer doesn't want this... 
    		//NumberFormat currency = NumberFormat.getCurrencyInstance();
    		
    		//DecimalFormat for two decimals places for the output text views...  
    		DecimalFormat decimalFormat = new DecimalFormat(".00");
    		
    		//Output
    		etTotalPay.setText(decimalFormat.format(totalPay));
    		etFedWH.setText(decimalFormat.format(fedWH));
    		etStateWH.setText(decimalFormat.format(stateWH));
    		etNetPay.setText(decimalFormat.format(totalNet));
    	}
    }
    
    //Checks for all errors including for negative numbers but i couldn't find a way to enter in negative numbers on the emulator... 
    public Boolean checkForErrorsOnCalculate(){
    	//Added this extra one for security reasons don't do a calculate until they log in
    	//for example if past hours and pay rate is already there then this will not let
    	//them calculate the values till they log in
    	if(!etHours.isEnabled() && !etPayRate.isEnabled()){
    		new AlertDialog.Builder(this)
    			.setTitle(getResources().getString(R.string.loginOnCalculateErrorTitle))
    			.setMessage(getResources().getString(R.string.loginOnCalculateErrorMessage))
    			.setNeutralButton(getResources().getString(R.string.neutralButton1), null)
  		  		.show();
    		return true;
    	}
    	//Normal checks for null that were in PayCalculator1.0
    	else if(etHours.isEnabled() && etPayRate.isEnabled()){
	    	if(etHours.getText().toString().isEmpty() || etPayRate.getText().toString().isEmpty())
	    	{
	    		//Checks to see if both inputs are blank
	    		if(etHours.getText().toString().isEmpty() && etPayRate.getText().toString().isEmpty()){
		    		new AlertDialog.Builder(this)
		    		  .setTitle(getResources().getString(R.string.nullHoursPayRateErrorTitle))
		    		  .setMessage(getResources().getString(R.string.nullHoursPayRateErrorMessage))
		    		  .setNeutralButton(getResources().getString(R.string.neutralButton1), null)
		    		  .show();
		    		return true;
	    		}
	    		//Checks to see if hour is blank
	    		else if(etHours.getText().toString().isEmpty()){
		    		new AlertDialog.Builder(this)
		    		  .setTitle(getResources().getString(R.string.nullHoursErrorTitle))
		    		  .setMessage(getResources().getString(R.string.nullHoursErrorMessage))
		    		  .setNeutralButton(getResources().getString(R.string.neutralButton1), null)
		    		  .show();
		    		return true;
		    		
	    		}
	    		//Checks to see if pay rate is blank
	    		else if(etPayRate.getText().toString().isEmpty()){
		    		new AlertDialog.Builder(this)
		    		  .setTitle(getResources().getString(R.string.nullPayRateErrorTitle))
		    		  .setMessage(getResources().getString(R.string.nullPayRateErrorMessage))
		    		  .setNeutralButton(getResources().getString(R.string.neutralButton1), null)
		    		  .show();
		    		return true;
	    		}
	    		//Checks for any other unexpected errors like they somehow entered in a alpha even though that doesn't seem possible.. 
	    		else{   			
	    			new AlertDialog.Builder(this)
	    			  .setTitle(getResources().getString(R.string.fatalErrorTitle))
		    		  .setMessage(getResources().getString(R.string.fatalErrorMessage))
		    		  .setNeutralButton(getResources().getString(R.string.neutralButton1), null)
					  .show(); 
	    			return true;
	    		}
	    	}
	    	else{
	    		//Checks if somehow they entered in a negative number, i tried this in the emulator and it wasn't possible. 
	    		if(Float.parseFloat(etHours.getText().toString()) < 0 || Float.parseFloat(etPayRate.getText().toString()) < 0){
	    			new AlertDialog.Builder(this)
	    			  .setTitle(getResources().getString(R.string.positiveNumberHoursPayRateErrorTitle))
		    		  .setMessage(getResources().getString(R.string.positiveNumberHoursPayRateErrorMessage))
	    			  .setNeutralButton(getResources().getString(R.string.neutralButton1), null)
		    		  .show();
	  			return true;
	    		}
	    		return false;
	    	}
    	}
    	else{
    		new AlertDialog.Builder(this)
    		.setTitle(getResources().getString(R.string.fatalErrorTitle))
  		  	.setMessage(getResources().getString(R.string.fatalErrorMessage))
  		  	.setNeutralButton(getResources().getString(R.string.neutralButton1), null)
			  .show(); 
			return true;
    	}
    }
    
    //This forces them to not have empty usernames and paswords.. but a specific can be specified.. 
    public Boolean checkForErrorsOnLogin(){
    	if(this.etUserName.getText().toString().isEmpty() || this.etPassword.getText().toString().isEmpty()){
    		new AlertDialog.Builder(this)
    			.setTitle(getResources().getString(R.string.loginGeneralErrorTitle))
  		  		.setMessage(getResources().getString(R.string.loginGeneralMessageError))
    			.setNeutralButton(getResources().getString(R.string.neutralButton1), null)
  		  		.show();
    		return true;
    	}
    		return false;
    }
    
    //gets total pay give hours and payRate.. and calculates overtime if over 40 hours.. 
    public Float getTotalPay(Float hours, Float payRate){
    	Float totalPay; 
    	if(hours > 40){
			totalPay = 40 * payRate;
			totalPay += (hours - 40) * payRate * overTimePayRate;
		}
		else{
			totalPay = hours * payRate;
		}
    	return totalPay;
    }
    
    // Gets federal tax rate using your gross pay
    public Float getFederalTaxRate(Float totalPay){
    	Float fedWH = (float) (totalPay * fedTaxRate);
    	return fedWH;
    }
    
    //Gets state tax rate using your gross pay
    public Float getStateTaxRate(Float totalPay){
    	Float stateWH = (float) (totalPay * stateTaxRate);
    	return stateWH;
    }
    
    //Calculates total of deductions.. added this in case we have more deductions
    public Float getTotalDeductions(Float... deductions){
    	Float totalDeductions = new Float(0); 
    	for(Float deduction : deductions){
    		totalDeductions += deduction;
    	}
    	return totalDeductions;
    }
    
    //Calculates net pay using gross pay minus array of deductions
    public Float getNetPay(Float totalPay, Float deductions){
    	Float totalNet = totalPay - deductions;
    	return totalNet;
    }
    
    //For clear button if its clicked clears all values and puts(REQUESTS) the focus on hours
    public void doClear(View view)
    {
        etHours.setText("");
        etPayRate.setText("");
        etTotalPay.setText("");
        etFedWH.setText("");
        etStateWH.setText("");
        etNetPay.setText("");
        etHours.requestFocus();
    }
    
    //Function that checks log in info... 
    public void doLogin(View view){
    	if(!checkForErrorsOnLogin()){
    		String userPassword = users.get(etUserName.getText().toString());

    		//This error message is the same as if either input or null or the password 
    		//is incorrect this can be changed did this so user can't guess a password combination
    		if(!etPassword.getText().toString().equals(userPassword)){
    			new AlertDialog.Builder(this)
    			  .setTitle(getResources().getString(R.string.loginGeneralErrorTitle))
	    		  .setMessage(getResources().getString(R.string.loginGeneralMessageError))
    			  .setNeutralButton(getResources().getString(R.string.neutralButton1), null)
	    		  .show();
    			
    			/*Can be used to reset the two edit texts after wrong entry if need be... */ 
    			//this.etUserName.setText("");
    			//this.etPassword.setText("");
    		}
    		//Checks to make sure password entered matches with password in the map.
    		else if(etPassword.getText().toString().equals(userPassword)){
    			new AlertDialog.Builder(this)
    			  .setTitle(getResources().getString(R.string.loginSuccesfulAlertTitle))
	    		  .setMessage(getResources().getString(R.string.loginSuccesfulAlertMessage))
    			  .setNeutralButton(getResources().getString(R.string.neutralButton1), null)
	    		  .show();
    			this.etUserName.setText("");
    			this.etPassword.setText("");
    			this.etHours.setEnabled(true);
    			this.etPayRate.setEnabled(true);
    			this.etHours.setFocusableInTouchMode(true);
    			this.etPayRate.setFocusableInTouchMode(true);
      		}
    		else{
    			new AlertDialog.Builder(this)
	    		  .setTitle(getResources().getString(R.string.fatalErrorTitle))
	    		  .setMessage(getResources().getString(R.string.fatalErrorMessage))
	    		  .setNeutralButton(getResources().getString(R.string.neutralButton1), null)
	    		  .show();
    			this.etUserName.setText("");
    			this.etPassword.setText("");
    			
    		}
    	}
    }
    
    
    //On destroy meaning when the app closes it will check if the hours and payrate are empty and if they aren't
    //it will store this information in the file... 
    public void onDestroy(){
    	super.onDestroy();
		try {
			if(!this.etHours.getText().toString().isEmpty() && !this.etPayRate.getText().toString().isEmpty())
			{
				OutputStreamWriter out = new OutputStreamWriter(openFileOutput(NOTES, 0));
				out.write(this.etHours.getText().toString()+ "," + this.etPayRate.getText().toString());
				out.close();		
			}
			else{
				//I know you hate toast but i didn't want to force the user to click out of this... i just
				//wanted to kinda show it but not show so i used toast.. 
				
				//Here is the code to get rid of the cached file if need be... 
				/*if(deleteFile(NOTES)){
					Toast.makeText(this,getResources().getString(R.string.succesfullyDeletedFile), Toast.LENGTH_LONG).show();		
				}*/
				
				//Just tells the user there was nothing to save.. used a toast because they shouldn't be required to 
				//click out of it.. 
				Toast.makeText(this,getResources().getString(R.string.warningDidNotSaveFile), Toast.LENGTH_LONG).show();	
			}
		}
		catch (Throwable t) {
			Toast.makeText(this, "Exception: "+t.toString(), Toast.LENGTH_LONG).show();
		}
    }
}